package com.easyfun.healthmagicbox.ormlite;

import java.sql.SQLException;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

import com.easyfun.healthmagicbox.comm.HealthThreadPool;
import com.easyfun.healthmagicbox.comm.ReferenceDataDescriptionDownloadTask;
import com.easyfun.healthmagicbox.pojo.AlarmClock;
import com.easyfun.healthmagicbox.pojo.ConstantData;
import com.easyfun.healthmagicbox.pojo.DataReferenceDescription;
import com.easyfun.healthmagicbox.pojo.DoctorAndDisease;
import com.easyfun.healthmagicbox.pojo.DoctorAndSuggestion;
import com.easyfun.healthmagicbox.pojo.DoctorProfile;
import com.easyfun.healthmagicbox.pojo.HealthInputData;
import com.easyfun.healthmagicbox.pojo.DoctorAndHospital;
import com.easyfun.healthmagicbox.pojo.PersonProfile;
import com.easyfun.healthmagicbox.pojo.PersonQuestion;
import com.easyfun.healthmagicbox.pojo.Picture;
import com.easyfun.healthmagicbox.pojo.TopHealth;
import com.easyfun.healthmagicbox.pojo.User;
import com.easyfun.healthmagicbox.pojo.UserToPersons;
import com.easyfun.healthmagicbox.sync.BasicCommCallback;
import com.easyfun.healthmagicbox.sync.CommCallback;
import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.TableUtils;

public class DatabaseHelper extends OrmLiteSqliteOpenHelper{
	// name of the database file for your application -- change to something appropriate for your app
		private static final String DATABASE_NAME = "healthbox.db";
		// any time you make changes to your database objects, you may have to increase the database version
		private static final int DATABASE_VERSION = 28;

		// the DAO object we use to access the PersonProfile table
		private Dao<PersonProfile, Integer> simpleDao = null;
		private Dao<HealthInputData, Integer> inputDao = null;
		private Dao<DoctorProfile, Integer> doctorProfileDao = null;
		private Dao<DoctorAndDisease, Integer> doctorDiseaseDao;
		private Dao<DoctorAndSuggestion, Integer> doctorSuggestionDao = null;
		private Dao<DoctorAndHospital, Integer> hospitalProfileDao;		
		private Dao<PersonQuestion, Integer> questionsDao;
		private Dao<User, Integer> userDao;
		private Dao<UserToPersons, Integer> userToPersonsDao;
		private Dao<TopHealth, Integer> topDao = null;
		private Dao<Picture, Integer> pictureDao = null;
		private Dao<AlarmClock, Integer> alarmclockDao = null;
		private Dao<DataReferenceDescription, Integer> dataReferenceDao = null;
		
		public DatabaseHelper(Context context) {
			super(context, DATABASE_NAME, null, DATABASE_VERSION);
		}
		
		

		/**
		 * This is called when the database is first created. Usually you should call createTable statements here to create
		 * the tables that will store your data.
		 */
		@Override
		public void onCreate(SQLiteDatabase db, ConnectionSource connectionSource) {
			try {
				Log.i(DatabaseHelper.class.getName(), "onCreate");
				/**
				 * create required tables
				 */
				TableUtils.createTable(connectionSource, PersonProfile.class);
				TableUtils.createTable(connectionSource, HealthInputData.class);
				TableUtils.createTable(connectionSource, DoctorProfile.class);
				TableUtils.createTable(connectionSource, DoctorAndDisease.class);
				TableUtils.createTable(connectionSource, DoctorAndSuggestion.class);
				TableUtils.createTable(connectionSource, DoctorAndHospital.class);
				TableUtils.createTable(connectionSource, PersonQuestion.class);
				TableUtils.createTable(connectionSource, User.class);
				TableUtils.createTable(connectionSource, UserToPersons.class);
				TableUtils.createTable(connectionSource, TopHealth.class);
				TableUtils.createTable(connectionSource, Picture.class);
				TableUtils.createTable(connectionSource, AlarmClock.class);
				TableUtils.createTable(connectionSource, DataReferenceDescription.class);
				
				/*create referenceData */
				//createReferenceData();
				
				
				// here we try inserting data in the on-create as a test
				//Dao<PersonProfile, Integer> dao = getPersonProfileDao();
				//long millis = System.currentTimeMillis();
				
				
				// create some entries in the onCreate
				//PersonProfile simple = new PersonProfile();
				//simple.setAge(10);
				//simple.setPersonID("99000118573-119");
				//simple.setImageFileName("");
				
				//dao.create(simple);
				
				//simple = new PersonProfile();
				//dao.create(simple);
				//Log.i(DatabaseHelper.class.getName(), "created new entries in onCreate: " + millis);
			} catch (SQLException e) {
				Log.e(DatabaseHelper.class.getName(), "Can't create database", e);
				throw new RuntimeException(e);
			}
		}

		/**
		 * This is called when your application is upgraded and it has a higher version number. This allows you to adjust
		 * the various data to match the new version number.
		 */
		@Override
		public void onUpgrade(SQLiteDatabase db, ConnectionSource connectionSource, int oldVersion, int newVersion) {
			try {
				Log.i(DatabaseHelper.class.getName(), "onUpgrade");
				TableUtils.dropTable(connectionSource, PersonProfile.class, true);
				TableUtils.dropTable(connectionSource, HealthInputData.class, true);
				TableUtils.dropTable(connectionSource, DoctorProfile.class, true);
				TableUtils.dropTable(connectionSource, DoctorAndDisease.class, true);
				TableUtils.dropTable(connectionSource, DoctorAndSuggestion.class, true);
				TableUtils.dropTable(connectionSource, DoctorAndHospital.class, true);
				TableUtils.dropTable(connectionSource, PersonQuestion.class,true);
				TableUtils.dropTable(connectionSource, User.class,true);
				TableUtils.dropTable(connectionSource, UserToPersons.class,true);
				TableUtils.dropTable(connectionSource, TopHealth.class, true);
				TableUtils.dropTable(connectionSource, Picture.class, true);
				TableUtils.dropTable(connectionSource, AlarmClock.class, true);
				TableUtils.dropTable(connectionSource, DataReferenceDescription.class, true);
				// after we drop the old databases, we create the new ones
				onCreate(db, connectionSource);
			} catch (SQLException e) {
				Log.e(DatabaseHelper.class.getName(), "Can't drop databases", e);
				throw new RuntimeException(e);
			}
		}

		/**
		 * Returns the Database Access Object (DAO) for our PersonProfile class. It will create it or just give the cached
		 * value.
		 */
		public Dao<PersonProfile, Integer> getPersonProfileDao() throws SQLException {
			if (simpleDao == null) {
				simpleDao = getDao(PersonProfile.class);
			}
			return simpleDao;
		}
		/**
		 * Returns the Database Access Object (DAO) for our HealthInputData class. It will create it or just give the cached
		 * value.
		 */
		public Dao<HealthInputData, Integer> getInputDataDao() throws SQLException {
			if (inputDao == null ) {
				inputDao = getDao(HealthInputData.class);
			}
			return inputDao;
		}
		
		/**
		 * Returns the Database Access Object (DAO) for our DoctorProfile class. It will create it or just give the cached
		 * value.
		 */
		public Dao<DoctorProfile, Integer> getDoctorProfileDao() throws SQLException {
			if (doctorProfileDao  == null ) {
				doctorProfileDao = getDao(DoctorProfile.class);
			}
			return doctorProfileDao;
		}
		
		/**
		 * Returns the Database Access Object (DAO) for our DoctorAndHospital class. It will create it or just give the cached
		 * value.
		 */
		public Dao<DoctorAndHospital, Integer> getHospitalDao() throws SQLException {
			if (hospitalProfileDao  == null ) {
				hospitalProfileDao = getDao(DoctorAndHospital.class);
			}
			return hospitalProfileDao;
		}
		
		/**
		 * Returns the Database Access Object (DAO) for our DoctorAndSuggestion class. It will create it or just give the cached
		 * value.
		 */
		public Dao<DoctorAndSuggestion, Integer> getDoctorSuggestionDao() throws SQLException {
			if (doctorSuggestionDao   == null ) {
				doctorSuggestionDao = getDao(DoctorAndSuggestion.class);
			}
			return doctorSuggestionDao;
		}
		
		/**
		 * Returns the Database Access Object (DAO) for our User class. It will create it or just give the cached
		 * value.
		 */
		public Dao<User, Integer> getUserDao() throws SQLException {
			if (userDao   == null ) {
				userDao = getDao(User.class);
			}
			return userDao;
		}
		/**
		 * Returns the Database Access Object (DAO) for our PersonQuestion class. It will create it or just give the cached
		 * value.
		 */
		public Dao<PersonQuestion, Integer> getQuestionsDao() throws SQLException {
			if (questionsDao   == null ) {
				questionsDao = getDao(PersonQuestion.class);
			}
			return questionsDao;
		}
		/**
		 * Returns the Database Access Object (DAO) for our DoctorAndDisease class. It will create it or just give the cached
		 * value.
		 */
		public Dao<DoctorAndDisease, Integer> getDoctorDiseaseDao() throws SQLException {
			if (doctorDiseaseDao   == null ) {
				doctorDiseaseDao = getDao(DoctorAndDisease.class);
			}
			return doctorDiseaseDao;
		}
		/**
		 * Returns the Database Access Object (DAO) for our UserToPersons class. It will create it or just give the cached
		 * value.
		 */
		public Dao<UserToPersons, Integer> getUserToPersonsDao() throws SQLException {
			if (userToPersonsDao   == null ) {
				userToPersonsDao = getDao(UserToPersons.class);
			}
			return userToPersonsDao;
		}
		
		public Dao<Picture, Integer> getPictureDao() throws SQLException {
			if (pictureDao == null ){
				pictureDao = getDao(Picture.class);
			}
			return pictureDao;
		}
		
		public Dao<AlarmClock, Integer> getAlarmClockDao() throws SQLException {
			if (alarmclockDao == null ){
				alarmclockDao = getDao(AlarmClock.class);
			}
			return alarmclockDao;
		}	
		
		public Dao<TopHealth, Integer> getTopDao() throws SQLException {
			if (topDao == null ){
				topDao = getDao(TopHealth.class);
			}
			return topDao;
		}
		
		public Dao<DataReferenceDescription, Integer> getReferenceDataDao() throws SQLException {
			if (dataReferenceDao == null) {
				dataReferenceDao = getDao(DataReferenceDescription.class);
			}
			return dataReferenceDao;
		}
		
		private void createReferenceData()
		{
			try {
				Dao<DataReferenceDescription, Integer> referenceDataDao = getReferenceDataDao();
				
				insertReferenceData(referenceDataDao, HealthInputTypeEnum.TIZHONG.toInteger(), 1, (float)60.0, (float)80.0, (float)170, (float)185.0, 0, "正常值范围：60KG-80KG");
	
				insertReferenceData(referenceDataDao, HealthInputTypeEnum.TIZHONG.toInteger(), 2, (float)50.0, (float)60.0, (float)140, (float)169.0, 0, "正常值范围：50KG-60KG");

				insertReferenceData(referenceDataDao, HealthInputTypeEnum.TIZHONG.toInteger(), 1, (float)30.0, (float)50.0, (float)110, (float)140.0, 0, "正常值范围：30KG-50KG");
/*				insertReferenceData(referenceDataDao, HealthInputTypeEnum.RUNKM.toInteger(), (float)5, (float)15, 0, "正常值范围：5-15Km");
				
				insertReferenceData(referenceDataDao, HealthInputTypeEnum.YINSHIKALULI.toInteger(), (float)2000, (float)2000, 0, "正常值范围：2000大卡");
				
				insertReferenceData(referenceDataDao, HealthInputTypeEnum.YANGWOQIZUO.toInteger(), (float)50, (float)100, 0, "正常值范围：50-100");*/
				
				insertReferenceData(referenceDataDao, HealthInputTypeEnum.SHENGAO.toInteger(), 2, (float)88.6, (float)102.9, (float)3, (float)3, 0, "正常值范围：88.6cm-102.9cm");
				insertReferenceData(referenceDataDao, HealthInputTypeEnum.SHENGAO.toInteger(), 2, (float)92.4, (float)106.8, (float)3.5, (float)3.5, 0, "正常值范围：92.4cm-106.8cm");
				insertReferenceData(referenceDataDao, HealthInputTypeEnum.SHENGAO.toInteger(), 2, (float)95.8, (float)110.6, (float)4, (float)4, 0, "正常值范围：95.8cm-110.6cm");
				insertReferenceData(referenceDataDao, HealthInputTypeEnum.SHENGAO.toInteger(), 2, (float)108.1, (float)125.5, (float)6, (float)6, 0, "正常值范围：108.1cm-125.5cm");
				insertReferenceData(referenceDataDao, HealthInputTypeEnum.SHENGAO.toInteger(), 2, (float)155.0, (float)175.0, (float)18, (float)60, 0, "正常值范围：155.0cm-175.0cm");
				
				//male
				insertReferenceData(referenceDataDao, HealthInputTypeEnum.SHENGAO.toInteger(), 1, (float)89.7, (float)104.1, (float)3, (float)3, 0, "正常值范围：89.7cm-104.1cm");
				insertReferenceData(referenceDataDao, HealthInputTypeEnum.SHENGAO.toInteger(), 1, (float)93.4, (float)108.1, (float)3.5, (float)3.5, 0, "正常值范围：93.4cm-108.1cm");
				insertReferenceData(referenceDataDao, HealthInputTypeEnum.SHENGAO.toInteger(), 1, (float)96.7, (float)111.8, (float)4, (float)4, 0, "正常值范围：96.7cm-111.8cm");
				insertReferenceData(referenceDataDao, HealthInputTypeEnum.SHENGAO.toInteger(), 1, (float)109.1, (float)126.6, (float)6, (float)6, 0, "正常值范围：109.1cm-126.6cm");
				insertReferenceData(referenceDataDao, HealthInputTypeEnum.SHENGAO.toInteger(), 1, (float)160.0, (float)190.0, (float)18, (float)60, 0, "正常值范围：160.0cm-190.0cm");

				
				//血糖
				insertReferenceData(referenceDataDao, HealthInputTypeEnum.XUETANG_CANHOU.toInteger(), ConstantData.REFERENCE_DATA_ANY, (float)3.9, (float)7.8, (float)ConstantData.REFERENCE_DATA_ANY, (float)ConstantData.REFERENCE_DATA_ANY, 0, "正常值范围：3.9mmol/L-7.8mmol/L");
				insertReferenceData(referenceDataDao, HealthInputTypeEnum.XUETANG_CANQIAN.toInteger(), ConstantData.REFERENCE_DATA_ANY, (float)3.9, (float)6.2, (float)ConstantData.REFERENCE_DATA_ANY, (float)ConstantData.REFERENCE_DATA_ANY, 0, "正常值范围：3.9mmol/L-6.2mmol/L");
				
				//血压低压
				insertReferenceData(referenceDataDao, HealthInputTypeEnum.XUEYA_DIYA.toInteger(), 1, (float)73, (float)82, (float)16, (float)65, 0, "正常值范围：73毫米汞柱-86毫米汞柱");
				insertReferenceData(referenceDataDao, HealthInputTypeEnum.XUEYA_DIYA.toInteger(), 2, (float)70, (float)83, (float)16, (float)65, 0, "正常值范围：70毫米汞柱-83毫米汞柱");

				//血压高压
				insertReferenceData(referenceDataDao, HealthInputTypeEnum.XUEYA_GAOYA.toInteger(), 1, (float)115, (float)148, (float)16, (float)65, 0, "正常值范围：115毫米汞柱-148毫米汞柱");
				insertReferenceData(referenceDataDao, HealthInputTypeEnum.XUEYA_GAOYA.toInteger(), 2, (float)110, (float)145, (float)16, (float)65, 0, "正常值范围：110毫米汞柱-145毫米汞柱");

				
				insertReferenceData(referenceDataDao, HealthInputTypeEnum.TIWEN.toInteger(), ConstantData.REFERENCE_DATA_ANY, (float)36, (float)37, (float)ConstantData.REFERENCE_DATA_ANY, (float)ConstantData.REFERENCE_DATA_ANY, 0, "正常值范围：36-37度");

			}catch(SQLException e){
				e.printStackTrace();
			}
			
		}
		private void insertReferenceData(Dao<DataReferenceDescription, Integer> referenceDataDao, 
										 int valueType, 
										 int gender, /*1: male, 2: female*/
										 float lowerLimitValue, 
										 float upperLimitValue, 
										 float dependencyLowerLimitValue,
										 float dependencyUpperLimitValue,
										 int syncId, String valueDescription)
		{
			try {
			DataReferenceDescription referenceData = new DataReferenceDescription();
			referenceData.setReferenceDataType(valueType);
			referenceData.setGender(gender);
			referenceData.setLowerLimitData(lowerLimitValue);
			referenceData.setUpperLimitData(upperLimitValue);
			referenceData.setDependencyLowerLimitData(dependencyLowerLimitValue);
			referenceData.setDependencyUpperLimitData(dependencyUpperLimitValue);
			referenceData.setReferenceDataDescription(valueDescription);
			referenceData.setSyncId(0);
			referenceDataDao.create(referenceData);
			}catch(SQLException e) {
				e.printStackTrace();
			}
		}
		/**
		 * Close the database connections and clear any cached DAOs.
		 */
		@Override
		public void close() {
			super.close();
			simpleDao = null;
		}
		
		public void clearDatabase()
		{
			onUpgrade(null, connectionSource, 1, 2);
		}
}
